﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using RedesII_WMI;
using RedesII_BLL;
using RedesII_DTL;

namespace redesII
{
    public partial class wmiForm : Form
    {

        //private ObjectQuery objQuery = new ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3");
        private ObjectQuery objQuerys = new ObjectQuery("Select * from Win32_LogicalDisk");
        private ManagementObjectSearcher searcher = null;
        private string query;
        private int cont = 0;
        int iAuxEquipment = -1;
        private static Socket sock;
        private static int pingstart, pingstop, elapsedtime;
        private bool isExecuting = false;

        public wmiForm()
        {
            InitializeComponent();
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
        }

        #region botoes
        //private void btnRun_Click(object sender, EventArgs e)
        //{

        //    if (cmbBusca.SelectedIndex < 0)
        //    {
        //        MessageBox.Show("Deve-se selecionar um tipo de busca",
        //            "Redes II", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        //        return;
        //    }

        //    TipoQuery tipoQuery = new TipoQuery();
        //    switch (cmbBusca.SelectedIndex)
        //    {
        //        case 0:
        //            tipoQuery = TipoQuery.process;
        //            break;
        //        case 1:
        //            tipoQuery = TipoQuery.hard_drive;
        //            break;
        //        case 2:
        //            tipoQuery = TipoQuery.ram_memory; //só de brincadeira
        //            break;
        //        default:
        //            break;
        //    }
        //    WMIProperties oProperties = new WMIProperties(tipoQuery);

        //    if (!chkTarget.Checked)
        //    {
        //        User user = new User(txtLogin.Text.Trim(), txtPWD.Text.Trim(), txtEstacao.Text.Trim());
        //        oProperties.BuscarDados(tipoQuery, user);
        //    }
        //    else { oProperties.BuscarDados(tipoQuery); }

        //    List<WMIField> properties = oProperties.Properties;

        //    //adiciona as colunas na listview.
        //    for (cont = 0; cont < oProperties.Qtd_campos; cont++)
        //    {
        //        lstItems.Columns.Add(properties[cont].Name);
        //    }

        //    cont = oProperties.Qtd_campos;
        //    int iQtd = 0;
        //    int iItem = -1;
        //    //adiciona as linhas na listview.
        //    for (int aux = 0; aux < properties.Count; aux++)
        //    {
        //        if (iQtd == cont || aux == 0)
        //        {
        //            lstItems.Items.Add(properties[aux].Value);
        //            iQtd = 0;
        //            iItem++;
        //        }
        //        else
        //        {
        //            lstItems.Items[iItem].SubItems.Add((properties[aux].Value == null || properties[aux].Value.Trim().Equals(string.Empty)) ? string.Empty : properties[aux].Value.Trim());
        //            iQtd++;
        //        }
        //    }

        //}

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

        //private void btnSave_Click(object sender, EventArgs e)
        //{
        //    List<WMIField> properties = new List<WMIField>();
        //    WMIField field = null;
        //    int iqtd = 0;
        //    foreach (ListViewItem item in lstItems.Items)
        //    {
        //        for (int aux = 0; aux < cont; aux++)
        //        {
        //            field = new WMIField();
        //            field.Name = lstItems.Columns[aux].Text;
        //            field.Value = lstItems.Items[iqtd].SubItems[aux].Text;
        //            properties.Add(field);
        //        }
        //        iqtd++;
        //    }

        //    WMIProperties oProperties = new WMIProperties();
        //    oProperties.Salvar("INSERT INTO PROCESS_TABLE (ID,CAPTION) VALUES ('12','NOTEPAD.EXE'", properties);

        //}
        #endregion

        #region rede
        #region ping

        private void sendPing(string Machine)
        {
            int recv, i = 1;
            ICMP packet = new ICMP();
            packet.Type = 0x08;
            packet.Code = 0x00;
            Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 0, 2);
            byte[] data = Encoding.ASCII.GetBytes("wmi package");
            Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length);
            packet.MessageSize = data.Length + 4;
            int packetsize = packet.MessageSize + 4;
            packet.Checksum = 0;
            Buffer.BlockCopy(BitConverter.GetBytes(i), 0, packet.Message, 2, 2);
            UInt16 chcksum = packet.getChecksum();
            packet.Checksum = chcksum;
            pingstart = Environment.TickCount;
            IPHostEntry iphe = Dns.Resolve(Machine);
            IPEndPoint iep = new IPEndPoint(iphe.AddressList[0], 0);
            EndPoint ep = (EndPoint)iep;
            sock.SendTo(packet.getBytes(), packetsize, SocketFlags.None, ep);
            try
            {
                data = new byte[1024];
                recv = sock.ReceiveFrom(data, ref ep);
                pingstop = Environment.TickCount;
                elapsedtime = pingstop - pingstart;

                if (lstDisp.InvokeRequired)
                {
                    if (!lstDisp.Items.Contains(iep.Address.ToString()))
                    {
                        methodInvokeCall(lstDisp, "Items.Add", new object[] { iep.Address.ToString() + " -> " + iphe.HostName.ToString().ToUpper() });
                    }
                }
                else
                {
                    if (!lstDisp.Items.Contains(ep.ToString()))
                    {
                        lstDisp.Items.Add(ep.ToString());
                    }
                }

            }
            catch (SocketException)
            {
                if (lstDisp.InvokeRequired)
                {
                    //methodInvokeCall(lstDisp, "Items.Add", new object[] { "ip não encontrado " + ep.ToString() });
                }
                else
                {
                    //lstDisp.Items.Add("ip não encontrado " + ep.ToString());
                }
            }
        }

        private delegate void methodInvokeCallDelegate(Control control, string methodName, object[] parameters);

        private void methodInvokeCall(Control control, string methodName, object[] parameters)
        {

            string propertyName = string.Empty;

            string propertyMethodName = string.Empty;



            if (control.InvokeRequired)
            {

                control.Invoke(new methodInvokeCallDelegate(methodInvokeCall), new object[] { control, methodName, parameters });

                return;

            }



            if (methodName.IndexOf(".") > 0)
            {

                propertyName = methodName.Split(new char[] { '.' }, 2)[0];

                propertyMethodName = methodName.Split(new char[] { '.' }, 2)[1];



                object controlProperty;

                controlProperty = control.GetType().GetProperty(propertyName).GetValue(control, null);



                Type[] types = new Type[parameters.Length];

                for (int index = 0; index < parameters.Length; index++)
                {

                    types[index] = parameters[index].GetType();

                }



                System.Reflection.MethodInfo oMethod = controlProperty.GetType().GetMethod(propertyMethodName, types);

                oMethod.Invoke(controlProperty, parameters);

            }

            else
            {

                control.GetType().GetMethod(methodName).Invoke(control, parameters);

            }

        }

        #endregion
        private void cmdLoadRange_Click(object sender, EventArgs e)
        {
            if (!txtBegin.Text.Equals("") && !txtEnd.Text.Equals(""))
            {
                lstDisp.Items.Clear();
                string[] rede = txtBegin.Text.Split('.');
                string[] range = txtEnd.Text.Split('.');
                string inicio = rede[0] + '.' + rede[1] + '.' + rede[2] + '.';
                string ip = txtBegin.Text;
                int fim = int.Parse(range[3]);
                int cont = int.Parse(rede[3]);
                bool oActive = false;
                Thread[] pinger = new Thread[2];
                while (cont <= fim)
                {
                    for (int posX = 0; ((posX < 2) && (cont <= fim)); posX++)
                    {
                        ip = String.Concat(inicio, (cont));
                        ThreadStart starter = new ThreadStart(delegate { sendPing(ip); });
                        pinger[posX] = new Thread(starter);
                        pinger[posX].IsBackground = true;
                        pinger[posX].Start();
                        cont++;
                    }
                    oActive = true;
                }
            }
        }

        private void endAutoComplete()
        {
            if (!txtEnd.Text.Equals(txtBegin.Text.ToString()))
            {
                txtEnd.Text = txtBegin.Text.ToString();
            }
        }

        private void txtBegin_KeyUp(object sender, KeyEventArgs e)
        {
            endAutoComplete();
        }

        private void cmdAdd_Click(object sender, EventArgs e)
        {
            if (!txtMachine.Text.Equals(""))
            {
                Thread pinger;
                ThreadStart starter = new ThreadStart(delegate { sendPing(txtMachine.Text); });
                pinger = new Thread(starter);
                pinger.IsBackground = true;
                pinger.Start();
            }
        }

        private void cmdAMon_Click(object sender, EventArgs e)
        {
            foreach (string lvi in lstDisp.SelectedItems)
            {
                if (!lstMoni.Items.Contains(lvi.Clone()))
                {
                    lstMoni.Items.Add(lvi.Clone());
                    //    lstDisp.Items.Remove(lvi.Clone());
                }
            }
        }

        private void cmdDel_Click(object sender, EventArgs e)
        {
            foreach (string lvi in lstMoni.SelectedItems)
            {
                if (!lstDisp.Items.Contains(lvi.Clone()))
                {
                    lstDisp.Items.Add(lvi.Clone());
                    //  lstMoni.Items.Remove(lvi.Clone());
                }
            }
        }
        private void cmdGo_Click(object sender, EventArgs e)
        {
            lstDiscos.Items.Clear();
            lstProcessadores.Items.Clear();
            lstProcessos.Items.Clear();
            lstSystem.Items.Clear();
            if (!isExecuting)
            {
                string[] Machine;
                foreach (String iIp in lstMoni.Items)
                {
                    Machine = iIp.Split('-');
                    string ip = Machine[0].Trim();
                    ListViewItem item = null;
                    //TODO: Ver com o Fabio como funciona isso
                    SalvaEquipamento(ip);
                    isExecuting = true;
                    cmdGo.Text = "Parar";
                    //para teste
                    //TODO: Alterar para pegar maquinas de uma lista
                    QueriesForWMI query = null;
                    if (chkSystem.Checked)
                    {
                        query = new QueriesForWMI(TipoQuery.system);
                        WMI_Access wmi_acess = new WMI_Access();
                        //List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", false);
                        List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", true);
                        if (properties.Count > 0)
                        {
                            foreach (WMI_Properties prop in properties)
                            {
                                item.Text = ip;
                                item.SubItems.Add(prop._valor);
                                lstSystem.Items.Add(item);
                            }
                        }
                    }
                    if (chkUsers.Checked)
                    {

                    }
                    if (chkProcess.Checked)
                    {
                        query = new QueriesForWMI(TipoQuery.process);
                        WMI_Access wmi_acess = new WMI_Access();
                        //List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", false);
                        List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", true);
                        if (properties.Count > 0)
                        {
                            foreach (WMI_Properties prop in properties)
                            {
                                item = new ListViewItem();
                                item.Text = ip;
                                item.SubItems.Add(prop._valor);
                                lstProcessos.Items.Add(item);
                                SalvaProcesso(prop._valor, ip);
                                //ServiceBo servico = new ServiceBo();
                                //servico.InsertService(new ServiceDto(prop._valor));
                            }
                        }
                    }
                    if (chkRam.Checked)
                    {
                    }
                    if (chkHardDrive.Checked)
                    {
                        query = new QueriesForWMI(TipoQuery.hard_drive);
                        WMI_Access wmi_acess = new WMI_Access();
                        //List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", false);
                        List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", true);
                        if (properties.Count > 0)
                        {
                            for (int cont = 0; cont < (properties.Count); cont++)
                            {
                                if (cont % 3 == 0 || cont == 0)
                                {
                                    item = new ListViewItem();
                                    item.Text = properties[cont + 1]._valor;
                                    item.SubItems.Add(properties[cont]._valor);
                                    item.SubItems.Add(properties[cont + 2]._valor);
                                    lstDiscos.Items.Add(item);
                                }
                            }
                        }
                    }
                    if (chkProcessor.Checked)
                    {
                        query = new QueriesForWMI(TipoQuery.processor);
                        WMI_Access wmi_acess = new WMI_Access();
                        //List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", false);
                        List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", true);
                        if (properties.Count > 0)
                        {
                            foreach (WMI_Properties prop in properties)
                            {
                                lstProcessadores.Items.Add(new ListViewItem(prop._valor));
                            }
                        }
                    }

                }
                cmdGo.Text = "Iniciar";
                isExecuting = false;
            }
            else
            {
                cmdGo.Text = "Iniciar";
                isExecuting = false;
            }

        }

        private void lstDisp_DoubleClick(object sender, EventArgs e)
        {
            lstMoni.Items.Add(lstDisp.SelectedItem.ToString());
        }

        private void lstMoni_DoubleClick(object sender, EventArgs e)
        {
            lstMoni.Items.Remove(lstMoni.SelectedItem);
        }

        private void tabconf_Click(object sender, EventArgs e)
        {

        }

        private void tabPage1_Click(object sender, EventArgs e)
        {

        }

        /// <summary>Salva o processo na base de dados</summary>
        /// <param name="processo"></param>
        private void SalvaProcesso(string processo, string ip)
        {
            ServiceBo serviceBO = new ServiceBo();
            ServiceDto service = serviceBO.GetByProcess(processo);
            if (service._Servico == null)
            {
                //inclui
                service = new ServiceDto();
                service._Servico = processo;
                serviceBO.InsertService(service);
                service = serviceBO.GetByProcess(processo);
            }
            SalvaProcessoEquipamento(service._IdServico, iAuxEquipment);
        }
        /// <summary>Salva o relacionamento de Serviço com Equipamento</summary>
        /// <param name="service">serviço que está sendo executado.</param>
        /// <param name="equipment">Equipamento aonde o serviço está sendo executado</param>
        private void SalvaProcessoEquipamento(int service, int equipment)
        {
            EquipmentServiceBo equipment_serviceBO = new EquipmentServiceBo();
            EquipmentServiceDto equipment_service = new EquipmentServiceDto();
            equipment_service._IdEquipamento = equipment;
            equipment_service._IdServico = service;
            equipment_serviceBO.InsertEquipmentService(equipment_service);
        }
        /// <summary>Salva o equipamento na base de dados</summary>
        /// <param name="ip">IP do equipamento que vai ser salvo na base.</param>
        private void SalvaEquipamento(string ip)
        {

            EquipmentBo equipmentBO = new EquipmentBo();
            EquipmentDto equipment = equipmentBO.GetByIp(ip);
            if (equipment == null)
            {
                //inclui
                equipment = new EquipmentDto();
                equipment._Ip = ip;
                equipment._Processador = BuscaProcessador(ip);
                equipment._PlacarRede = "t";
                equipmentBO.InsertEquipment(equipment);
                equipment= equipmentBO.GetByIp(ip);
            }
            iAuxEquipment = equipment._IdEquipamento;
        }
        /// <summary>Pega o ip da maquina e busca o processador referente a mesma</summary>
        /// <param name="ip">ip da maquina</param>
        /// <returns>Retorna a descrição do processador</returns>
        private string BuscaProcessador(string ip)
        {

            QueriesForWMI query = null;
            query = new QueriesForWMI(TipoQuery.processor);
            WMI_Access wmi_acess = new WMI_Access();
            //TODO: Alterar esse tipo de chamada.
            //List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", false);
            List<WMI_Properties> properties = wmi_acess.ExecutaQueryWMI(query.Query, "", true);
            if (properties.Count > 0)
            {
                foreach (WMI_Properties prop in properties)
                {
                    return prop._valor;
                }
            }

            return string.Empty;
        }
    }
    //Fim da Form Class

    class ICMP
    {
        public byte Type;
        public byte Code;
        public UInt16 Checksum;
        public int MessageSize;
        public byte[] Message = new byte[1024];

        public ICMP()
        {
        }

        public ICMP(byte[] data, int size)
        {
            Type = data[20];
            Code = data[21];
            Checksum = BitConverter.ToUInt16(data, 22);
            MessageSize = size - 24;
            Buffer.BlockCopy(data, 24, Message, 0, MessageSize);
        }

        public byte[] getBytes()
        {
            byte[] data = new byte[MessageSize + 9];
            Buffer.BlockCopy(BitConverter.GetBytes(Type), 0, data, 0, 1);
            Buffer.BlockCopy(BitConverter.GetBytes(Code), 0, data, 1, 1);
            Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, data, 2, 2);
            Buffer.BlockCopy(Message, 0, data, 4, MessageSize);
            return data;
        }

        public UInt16 getChecksum()
        {
            UInt32 chcksm = 0;
            byte[] data = getBytes();
            int packetsize = MessageSize + 8;
            int index = 0;

            while (index < packetsize)
            {
                chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index));
                index += 2;
            }
            chcksm = (chcksm >> 16) + (chcksm & 0xffff);
            chcksm += (chcksm >> 16);
            return (UInt16)(~chcksm);
        }
    }
        #endregion

}